package com.qf.cx.simplenms.subscriber.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import com.qf.cx.simplenms.subscriber.api.Subscriber;
import com.qf.cx.simplenms.subscriber.api.SubscriberManager;
import com.qf.cx.simplenms.subscriber.model.SubscriberModel;
import com.qf.cx.simplenms.subscriber.spi.SubscriberSpi;
import com.qf.cx.simplenms.subscriber.type.exception.InvalidURIException;

@Service
@PropertySource("classpath:subscriber.properties")
public class SubscriberManagerImpl implements SubscriberManager {
	private Logger logger = LoggerFactory.getLogger(this.getClass());
	private Map<String, SubscriberSpi> cache = new HashMap<>();

	@Autowired
	private Environment env;

	@Override
	public synchronized Subscriber getSubscriber(String url) {
		SubscriberSpi subscriber = cache.get(url);
		if (subscriber == null) {
			logger.warn("no subscriber named '{}'", url);
		}
		return subscriber;
	}

	@Override
	public synchronized void updateCache(List<SubscriberModel> list) {
		for (Iterator<Entry<String, SubscriberSpi>> it = cache.entrySet().iterator(); it.hasNext();) {
			Entry<String, SubscriberSpi> e = it.next();

			boolean delete = true;
			for (SubscriberModel subscriberModel : list) {
				if (subscriberModel.getUrl().equals(e.getKey())) {
					delete = false;
					break;
				}
			}
			if (delete) {
				SubscriberSpi subscriber = e.getValue();
				subscriber.forceStop();
				it.remove();
				logger.debug("delete subscriber '{}'", e.getKey());
			}
		}

		for (SubscriberModel t : list) {
			SubscriberSpi subscriber = cache.get(t.getUrl());
			try {
				if (subscriber == null) {
					subscriber = new SubscriberImpl(Integer.parseInt(env.getProperty("queueSize", "100")), t);
					cache.put(t.getUrl(), subscriber);
					logger.debug("add subscriber '{}'", t.getUrl());
				} else {
					subscriber.updateSubscriberModel(t);
					logger.debug("update subscriber '{}'", t.getUrl());
				}
			} catch (InvalidURIException e) {
				logger.error("", e);
			}
		}

	}

	@Override
	public synchronized String dump() {
		StringBuilder sb = new StringBuilder();
		sb.append("<h1>subscribers</h1></br>");
		for (Entry<String, SubscriberSpi> entry : cache.entrySet()) {
			sb.append(entry.getKey()).append("</br>").append(entry.getValue().dump()).append("</br>");
		}
		sb.append("</br>");
		return sb.toString();
	}

	@Override
	public synchronized List<Subscriber> getSubscribers() {
		List<Subscriber> list = new ArrayList<>(cache.values());
		return list;
	}

}
